package com.yeskery.nut.http;

import com.yeskery.nut.application.NutApplication;
import com.yeskery.nut.bind.HttpResponseBodyHandler;
import com.yeskery.nut.bind.HttpResponseBodyMetadata;
import com.yeskery.nut.core.NameAndValue;
import com.yeskery.nut.core.Order;
import com.yeskery.nut.core.Response;
import com.yeskery.nut.util.http.ResponseEntity;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * {@link ResponseEntity} 响应体处理器
 * @author YESKERY
 * 2024/10/11
 */
public class ResponseEntityHttpResponseBodyHandler implements HttpResponseBodyHandler {

    @Override
    public boolean support(HttpResponseBodyMetadata metadata) {
        return ResponseEntity.class.isAssignableFrom(metadata.getResult().getClass());
    }

    @Override
    public void handle(HttpResponseBodyMetadata metadata) {
        Response response = metadata.getResponse();
        ResponseEntity<?> responseEntity = (ResponseEntity<?>) metadata.getResult();
        Integer status;
        if ((status = responseEntity.getStatus()) != null) {
            response.setCode(status);
        }
        List<NameAndValue> headers;
        if ((headers = responseEntity.getHeaders()) != null) {
            for (NameAndValue nameAndValue : headers) {
                response.addHeader(nameAndValue);
            }
        }
        List<HttpResponseBodyHandler> httpResponseBodyHandlers = new ArrayList<>(metadata.getApplicationContext()
                .getBean(NutApplication.class).getNutWebConfigure().getHttpResponseBodyHandlers());
        httpResponseBodyHandlers.sort(Comparator.comparing(Order::getOrder));
        metadata.setResult(responseEntity.getBody());
        boolean handled = false;
        for (HttpResponseBodyHandler handler : httpResponseBodyHandlers) {
            if (!(handler instanceof ResponseEntityHttpResponseBodyHandler) && handler.support(metadata)) {
                handler.handle(metadata);
                handled = true;
                break;
            }
        }
        if (!handled) {
            throw new HttpMediaTypeNotSupportException("ResponseEntity[type=" + responseEntity.getBody().getClass().getName()
                    + "] Produce Media Type[" + String.join(", ", metadata.getAttributes().getProduces()) + "] Not Support.");
        }
    }

    @Override
    public int getOrder() {
        return Order.MAX;
    }
}
